package nspel

import (
	"bytes"
	"encoding/gob"
	"github.com/gomodule/redigo/redis"
	"github.com/json-iterator/go"
	"strconv"
)

var redisPool *redis.Pool
var RedisDefaultLift int
var json = jsoniter.ConfigCompatibleWithStandardLibrary

func redisEngineInit(redisConfig Redis) {
	redisPool = &redis.Pool{
		MaxIdle:   redisConfig.MaxIdle,
		MaxActive: redisConfig.MaxOpen,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", redisConfig.Host+":"+strconv.Itoa(redisConfig.Port), redis.DialPassword(redisConfig.Password), redis.DialDatabase(redisConfig.DB))
			if err != nil {
				return nil, err
			}
			return c, nil
		},
	}
	RedisDefaultLift = redisConfig.LifeTime
}

func GetRedis() redis.Conn {
	return redisPool.Get()
}

func RedisIsExist(key string, model interface{}) bool {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	isExist, err := redis.Bool(redisConnection.Do("EXISTS", key))
	if err != nil {
		Error(err)
		return false
	}
	if !isExist {
		return false
	}
	reply, err := redis.String(redisConnection.Do("GET", key))
	if err != nil {
		Error(err)
		return false
	}
	err = json.Unmarshal([]byte(reply), model)
	if err != nil {
		Error(err)
		return false
	}
	return true
}

func ResdisWriteString(key string, value interface{}, lifeTime int64) {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	value, err := json.Marshal(value)
	if err != nil {
		Error(err)
	}
	_, err = redisConnection.Do("SET", key, value, "EX", lifeTime)
	if err != nil {
		Error(err)
	}
}

func RedisHgetInt64(key string, hashKey string) (int64, error) {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	result, err := redis.Int64(redisConnection.Do("hget", key, hashKey))
	return result, err
}

func RedisHgetString(key string, hashKey string) (string, error) {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	result, err := redis.String(redisConnection.Do("hget", key, hashKey))
	return result, err
}

func RedisHgetJson(key string, hashKey string, object interface{}) error {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	result, err := redis.Bytes(redisConnection.Do("hget", key, hashKey))
	if err != nil {
		return err
	}
	var buffer bytes.Buffer
	buffer.Write(result)
	dec := gob.NewDecoder(&buffer)
	err = dec.Decode(object)
	//err = json.Unmarshal([]byte(result), object)
	//if err != nil {
	//	return err
	//}
	return nil
}

func RedisHsetJson(key string, hashKey string, object interface{}) {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	//data, err := json.Marshal(object)
	//if err != nil {
	//	Error(err)
	//	return
	//}
	var buffer bytes.Buffer
	enc := gob.NewEncoder(&buffer)
	err := enc.Encode(object)
	if err != nil {
		Error(err)
		return
	}
	_, err = redisConnection.Do("hset", key, hashKey, buffer.Bytes())
	if err != nil {
		Error(err)
	}
}

func RedisHsetInt64(key string, hashKey string, object interface{}) {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	_, err := redisConnection.Do("hset", key, hashKey, object)
	if err != nil {
		Error(err)
	}
}

func RedisHmset(key string, hashMap interface{}) error {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	_, err := redisConnection.Do("hmset", redis.Args{}.Add(key).AddFlat(hashMap)...)
	return err
}

func RedisKeyDelete(key string) error {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	_, err := redisConnection.Do("DEL", key)
	return err
}

func ResdisKeysDelete(keys ...string) (err error) {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	for i := 0; i < len(keys); i++ {
		_, err = redisConnection.Do("DEL", keys[i])
	}
	return
}

func RedisLpush(key string, list interface{}) error {
	redisConnection := GetRedis()
	defer redisConnection.Close()
	_, err := redisConnection.Do("lpush", key, list)
	return err
}
